
/**
 * Copyright (c) 2024 - CARThunder
 * All Rights Reserved by Chengdu CARThunder Intelligent Technology Co., LTD and its affiliates.
 * You may not use, copy, distribute, modify, transmit in any form this file
 * except in compliance with CARThunder in writing by applicable law.
 * <p>
 * <p>
 * file description.
 *
 * @file filename
 * @brief brief function description.
 * @details detailed function description.
 * @version 1.0
 * @author author_name
 * @date last_modified_date
 * <p>
 * Edit History
 * ----------------------------------------------------------------------------
 * DATE                     NAME               DESCRIPTION
 * 2024-07-30              junjieluo         Create it.
 * <p>
 * file description.
 * @file filename
 * @brief brief function description.
 * @details detailed function description.
 * @version 1.0
 * @author author_name
 * @date last_modified_date
 * <p>
 * Edit History
 * ----------------------------------------------------------------------------
 * DATE                     NAME               DESCRIPTION
 * 2024-07-30              zhihua.zhang         Create it.
 */

/**
 * file description.
 * @file filename
 * @brief brief function description.
 * @details detailed function description.
 * @version 1.0
 * @author author_name
 * @date last_modified_date
 *
 *      Edit History
 *      ----------------------------------------------------------------------------
 *      DATE                     NAME               DESCRIPTION
 *      2024-07-30              zhihua.zhang         Create it.
 *
 */

package com.cart.musicdemo.base.service;

import android.media.MediaMetadataRetriever;
import android.util.Log;


import com.cart.musicdemo.model.SongModel;

import java.io.File;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * The type Batch song retriever.
 */
public class BatchSongRetriever {
    /**
     * 工作线程池大小.
     */
    private static final int WORKER_POOL_SIZE = Runtime.getRuntime().availableProcessors();

    /**
     * 固定大小为CPU核数的线程池.
     */
    private static final ExecutorService RETRIEVE_EXECUTORS
            = Executors.newFixedThreadPool(WORKER_POOL_SIZE);

    /**
     * 对象池.
     */
    private static final BlockingQueue<Worker> WORKER_POOL
            = new ArrayBlockingQueue<>(WORKER_POOL_SIZE);

    private static final String TAG = BatchSongRetriever.class.getName();

    /**
     * Instantiates a new Batch song retriever.
     */
    public BatchSongRetriever() {
        // 初始化对象池
        for (int i = 0; i < WORKER_POOL_SIZE; i++) {
            WORKER_POOL.offer(new Worker());
        }
    }

    /**
     * Retrieve future.
     *
     * @param file the file
     * @return the future
     * @throws InterruptedException the interrupted exception
     */
    public Future<SongModel> retrieve(File file) throws InterruptedException {
        Worker worker = WORKER_POOL.take();
        return RETRIEVE_EXECUTORS.submit(worker.setFile(file));
    }

    private static class Worker implements Callable<SongModel> {

        private File file;

        private final MediaMetadataRetriever mmr;

        /**
         * Instantiates a new Worker.
         */
        public Worker() {
            this.mmr = new MediaMetadataRetriever();
        }

        @Override
        public SongModel call() throws Exception {
            try {
                return parseAudioFile(file);
            } finally {
                // 处理后将这个Worker返回到对象池中
                WORKER_POOL.offer(this);
            }
        }

        private SongModel parseAudioFile(File file) {
            // 创建一个新的 SongModel 对象，用于存储音频文件的元数据
            SongModel songModel = new SongModel();
            try {
                // 设置数据源为传入的音频文件的绝对路径
                mmr.setDataSource(file.getAbsolutePath());

                // 设置 SongModel 对象的路径属性为音频文件的绝对路径
                songModel.setPath(file.getAbsolutePath());

                // 设置 SongModel 对象的大小属性为音频文件的长度（以字节为单位）
                songModel.setSize(file.length());

                // 提取音频文件的标题元数据，如果没有标题则使用文件名代替
                String name = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
                songModel.setName(
                        name == null || name.isEmpty() ? file.getName() : name
                );

                // 提取音频文件的艺术家元数据，并设置到 SongModel 对象中
                songModel.setSinger(
                        mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)
                );

                // 提取音频文件的专辑元数据，并设置到 SongModel 对象中
                songModel.setAlbum(
                        mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM)
                );

                // 提取音频文件的持续时间元数据（以毫秒为单位），并转换为整数后设置到 SongModel 对象中
                songModel.setDuration(
                        Integer.parseInt(
                                mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
                        )
                );
                // 返回包含元数据的 SongModel 对象
                return songModel;
            } catch (RuntimeException exception) {
                // 捕获无法解析音源的异常，并记录错误信息
                Log.e(TAG, exception.getMessage());
                return null;
            }
        }

        /**
         * Sets file.
         *
         * @param file the file
         * @return the file
         */
        public Worker setFile(File file) {
            this.file = file;
            return this;
        }
    }
}
